package com.wxd.framework.common.utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.wxd.framework.common.FrameConstants;

public class XMLUtils {
	
	/**
	 * 讲xml类型字符串转换成document对象
	 * @param xml
	 * @return
	 */
	public static Document parseStringToXml(String xml){
		Document doc = null;
		try{
			doc = DocumentHelper.parseText(xml);
		}catch(DocumentException ex){
			ex.printStackTrace();
		}
		return doc;
	}
	
	/**
	 * 读取xml文件
	 * @param filepath
	 * @return
	 */
	public static Document parseFileToXml(String filePath){
		SAXReader saxReader = new SAXReader();
		Document doc = null;
		try{
			doc = saxReader.read(new File(filePath));
		}catch(DocumentException ex){
			ex.printStackTrace();
		}
		return doc;
	}
	
	/**
	 * 获取webapp相对路径下的xml文件
	 * @param fileName
	 * @return
	 */
	public static Document parseFIOToXml(String fileName){
		return parseFIOToXml(fileName, FrameConstants.XML_PATH_DEFAULT);
	}
	
	/**
	 * 获取webapp相对路径下的xml文件
	 * @param fileName
	 * @param path 默认在xml文件夹下
	 * @return
	 */
	public static Document parseFIOToXml(String fileName, String path){
		SAXReader saxReader = new SAXReader();
		fileName = path + fileName;
		Document doc = null;
		try{
			InputStream inputStream = XMLUtils.class.getResourceAsStream(fileName);
			doc = saxReader.read(inputStream);
		}catch(DocumentException ex){
			ex.printStackTrace();
		}
		return doc;
	}
		
	/**
	 * 根据xpath 获取指定的元素
	 * @param xpath
	 * @param doc
	 * @return
	 */
	public static Element getElementByXpath(String xpath, Document doc){
		List<Element> list = doc.selectNodes(xpath);
		if (list != null && list.size() > 0) {
			return list.get(0);
		}else {
			return null;
		}
	}
	
	/**
	 * 根据id获取指定元素
	 * @param id
	 * @param doc
	 * @return
	 */
	public static Element getElementById(String id, Document doc){
		return getElementByXpath("//*[@id='"+id+"']",doc);  
	}
	
	/**
	 * 在指定id的元素后面插入元素
	 * @param pid
	 * @param newEle
	 * @param doc
	 * @return
	 */
	public static Document insertElement(String pid, Element newEle, Document doc){
		return insertElement(pid, newEle, doc, 1);
	}
	
	/**
	 * 在指定id的元素后面或前面插入元素
	 * @param pid
	 * @param newEle
	 * @param doc
	 * @param i 为1表示在坐标元素之后  为0表示在坐标元素之前
	 * @return
	 */
	public static Document insertElement(String pid, Element newEle, Document doc, int i){
		Element element = getElementById(pid, doc);//坐标元素
		List<Element> list = element.getParent().content();//获取坐标元素父元素下的所有元素
		list.add(list.indexOf(element)+i, newEle);
		return doc;
	}
	
	/**
	 * 删除文档doc的指定路径下的所有子节点（包含元素，属性等），如果路径相同一并删除
	 * @param doc 文档对象
	 * @param xpath
	 * @return
	 */
	public static boolean deleteNodes(Document doc, String xpath){
		boolean flag = true;
		try{
			List<Node> list = doc.selectNodes(xpath);
			for(Node node : list){
				node.detach();
			}
		}catch(Exception ex){
			flag = false;
		}
		return flag;
	}
	
	/**
	 * 删除一个父元素下所有的子节点（包含元素，属性等）
	 * @param element 父元素
	 * @return
	 */
	public static boolean deleteChildren(Element element){
		boolean flag = true;
		try{
			List<Node> list = element.elements();
			for(Node node : list){
				node.detach();
			}
		}catch(Exception ex){
			flag = false;
		}
		return flag;
	}
	
	/**
	 * 删除指定的元素
	 * @param element
	 * @return
	 */
	public static boolean deleteElement(Element element){
		List<Element> list = element.getParent().content();
		list.remove(list.indexOf(element));
		return true;
	}
	
	/**
	 * 保存xml
	 * @param filePath
	 * @param doc
	 * @return
	 */
	public static boolean saveDocument(String filePath, Document doc){
		try {
			XMLWriter writer = new XMLWriter(new FileWriter(new File(filePath)));
			writer.write(doc);
			writer.close();
			return true;
		} catch (IOException ex) {
			ex.printStackTrace();
			return false;
		}
	}
	

	/**
	 * 读取xml
	 * @param fileName
	 * @param t
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> readXml(String fileName, String path, T t){
		List<T> list = new ArrayList<>();
		try{
			Document doc = parseFIOToXml(fileName, path);
			Element root = doc.getRootElement();
			Element item;
			Field[] fields = t.getClass().getDeclaredFields();//获取属性集合
			Method getMethod;//get方法
			Method setMethod;//set方法
			String itemName = t.getClass().getSimpleName();
			for (Iterator iterator = root.elementIterator(itemName); iterator.hasNext();) {
				item = (Element)iterator.next();
				t = (T)t.getClass().newInstance();//创建对象的新的实例
				for(int i = 0; i<fields.length; i++){
					setMethod = t.getClass().getMethod("set"+fields[i].getName().substring(0, 1).toUpperCase()
							+fields[i].getName().substring(1), fields[i].getType());
					//将对应的节点的值存入
					setMethod.invoke(t, item.elementText(fields[i].getName()));					
				}
				list.add(t);
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return list;
	}
	
	/**
	 * 对象写入xmlABSOULTE
	 * @param obj
	 * @param list
	 * @param fileName
	 */
	public static <T> void writeXml(T obj, List<T> list,String absoultePath, String fileName){
		writeXml(obj, list, "UTF-8", absoultePath, fileName);
	}
	
	/**
	 * 对象写入xml
	 * @param obj
	 * @param list
	 * @param encode
	 * @param fileName
	 */
	public static <T> void writeXml(T obj, List<T> list, String encode, String absoultePath, String fileName){
		try{
			XMLWriter writer = null;
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding(encode);
			fileName = absoultePath + fileName;
			File file = new File(absoultePath);
			if (!file.exists() && !file.isDirectory()) {
				file.mkdir();
			}			
			file = new File(fileName);
			if (file.exists()) {
				file.delete();
			}
			Document document = DocumentHelper.createDocument();
			String rootName = obj.getClass().getSimpleName();//获得类名
			Element root = document.addElement(rootName + "s");
			Field[] fields = obj.getClass().getDeclaredFields();//获得实体类的所有属性
			for(T t : list){
				Element secondRoot = root.addElement(rootName);
				for(int i = 0; i < fields.length; i++){
					Method method = t.getClass().getMethod("get"+fields[i].getName().substring(0, 1).toUpperCase()
							+fields[i].getName().substring(1));
					secondRoot.addElement(fields[i].getName()).setText(method.invoke(t).toString());
				}
			}
			writer = new XMLWriter(new FileWriter(file), format);
			writer.write(document);
			writer.close();
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
}
